import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/services.dart';
import 'package:todo_app/constants/audio.dart';
import 'package:todo_app/pages/message/definitions/WrapMessage.dart';
import 'package:todo_app/utils/db/DBDataType.dart';
import 'package:todo_app/utils/db/DBHelper.dart';
import 'package:todo_app/utils/db/DBScheme.dart';
import 'package:todo_app/utils/mqtt/MessageEventBus.dart';

class MessageDBUtils {
  static MessageTable table = MessageTable();

  static init() async {
    await table.init();
  }

  static AudioPlayer audioPlayer = AudioPlayer();

  // 保存消息到本地
  static saveMessage(LocalMessage msg) async {
    if(msg.userId == null || msg.mid == null) return;
    var localMsg = await MessageDBUtils.queryMsgById(msg.mid!, msg.userId!);
    msg.updatedAt = DateTime.now();
    if(localMsg != null) {
      // 更新本地消息
      await table.update(msg);
    } else {
      // 插入本地消息
      await table.insert(msg);
      // 本地提示
      await audioPlayer.play(DeviceFileSource(AssetAudios.receivedMsg), mode: PlayerMode.lowLatency);
      HapticFeedback.heavyImpact();
    }
  }

  // 查询本地消息
  static Future<LocalMessage?> queryMsgById(String msgId, int userId) async {
    return await table.findOneById(msgId, userId);
  }

  // 查询本地聊天记录
  static Future<List<LocalMessage>> queryHistoryMsgList(int userId, MessageCategory category, int receivedId, {
    DateTime? before
  }) async {
    return await table.queryAllMessage(
      userId: userId, 
      otherId: receivedId, 
      category: category,
      utc: before
    );
  }
}

class MessageTable {
  DBHelper db = DBHelper(
    schemes: [
      DBScheme(columnName: "mid", columnType: DBDataType.TEXT),
      DBScheme(columnName: "category", columnType: DBDataType.TEXT, isNull: true),
      DBScheme(columnName: "viewType", columnType: DBDataType.TEXT, isNull: true, sinceFrom: 2),
      DBScheme(columnName: "type", columnType: DBDataType.TEXT, isNull: true),
      DBScheme(columnName: "crypto", columnType: DBDataType.TEXT, isNull: true),
      DBScheme(columnName: "content", columnType: DBDataType.TEXT, isNull: true),

      DBScheme(columnName: "suid", columnType: DBDataType.INTEGER, isNull: true),
      DBScheme(columnName: "rid", columnType: DBDataType.INTEGER, isNull: true),

      DBScheme(columnName: "send_time", columnType: DBDataType.INTEGER, isNull: true),
      DBScheme(columnName: "sending", columnType: DBDataType.BOOL, isNull: true),
      DBScheme(columnName: "sendError", columnType: DBDataType.BOOL, isNull: true),

      DBScheme(columnName: "userId", columnType: DBDataType.INTEGER, isNull: false),
      DBScheme(columnName: "createdAt", columnType: DBDataType.INTEGER, isNull: true),
      DBScheme(columnName: "updatedAt", columnType: DBDataType.INTEGER, isNull: true),
    ],
    tableName: "t_message_v1",
    dbPath: "t_message_v1_20230704.db",
    version: 2
  );

  Future init() async {
    await db.open();
  }

  Future dispose() async {
    await db.close();
  }

  Future<int> insert(LocalMessage message) async {
    message.createdAt = message.createdAt ?? DateTime.now().toUtc();
    message.updatedAt = message.updatedAt ?? DateTime.now().toUtc();
    return await db.insert(message.toJson());
  }

  Future<int> update(LocalMessage message) async {
    message.createdAt = message.createdAt ?? DateTime.now().toUtc();
    message.updatedAt = message.updatedAt ?? DateTime.now().toUtc();
    return await db.update(message.toJson(), "mid = ? AND userId = ?", [message.mid, message.userId]);
  }

  Future<int> deleteByUser(int mUserId, MessageCategory category, int userId) async {
    return await db.delete(null, "userId = ? AND category = ? AND (rid = ? OR suid = ?)", [userId, category.name, mUserId, mUserId]);
  }

  Future<LocalMessage?> findOneById(String mid, int userId) async {
    LocalMessage message = LocalMessage();
    Map<String,dynamic>? map = (await db.where("mid = ? AND userId = ?", [mid, userId]))?.first;
    if(map == null) return null;
    message.fromJson(map);
    return message;
  }
  // 查询某个时间点 以前的数据
  Future<List<LocalMessage>> queryAllMessage({ 
    required int userId,
    required int otherId,
    required MessageCategory category,
    DateTime? utc,
    int pageSize = 200,
  }) async {
    int createdAt = (utc ?? DateTime.now().toUtc()).millisecondsSinceEpoch;
    List<Map<String,dynamic>>? maps = await db.where(
      "userId = ? AND category = ? AND (rid = ? OR suid = ?) AND createdAt < ?", [userId, category.name, otherId, otherId, createdAt],
      limit: pageSize,
      orderBy: "send_time DESC"
    );
    return maps?.map((map)=>  LocalMessage()..fromJson(map)).toList() ?? <LocalMessage>[];
  }
}
